//
// Created by Jisam on 30/09/2024 4:22 PM.
// Solution of  数列分段 Section II
// 2024-09-30 16:38:11 AC 100 二分答案
#include <bits/stdc++.h>

#define  int long long
#define  endl "\n"
using namespace std;


signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int n, m; // 定义变量n（数组元素数量）和m（子数组的最大数量）
    cin >> n >> m; // 输入数组元素数量和子数组的最大数量
    vector<int> a(n); // 定义一个大小为n的vector，用于存储数组元素
    int left = 0, right = 0; // 定义变量left（二分查找的左边界），right（二分查找的右边界），初始right为0

    // 读取数组元素，并更新left和right
    for (int i = 0; i < n; i++) {
        cin >> a[i]; // 输入数组元素
        left = max(a[i], left); // 更新left为数组元素中的最大值
        right += a[i]; // 更新right为数组元素的总和
    }

    // 定义一个lambda函数check，用于检查给定的x值是否满足条件
    auto check = [&](int x) -> bool {
        int cnt = 1; // 定义变量cnt，用于计数满足条件的子数组数量
        int temp = 0; // 定义变量temp，用于存储当前子数组的和
        for (int i = 0; i < n; i++) {
            if (temp + a[i] <= x) { // 如果当前子数组的和加上数组元素a[i]不超过x
                temp += a[i]; // 更新当前子数组的和
            } else { // 否则
                cnt++; // 子数组数量加1
                temp = a[i]; // 重置当前子数组的和为当前元素的值
            }
        }
        return cnt <= m; // 返回子数组数量是否不超过m
    };

    // 使用二分查找算法找到满足条件的最小x值
    while (left + 1 < right) {
        int mid = (left + right) / 2; // 计算中间值
        (check(mid) ? right : left) = mid; // 如果check函数返回true，更新right为mid；否则更新left为mid
    }
    cout << right << endl; // 输出满足条件的最小x值
    return 0;
}